package com.csaba.connector.citi.parser;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;

import com.csaba.connector.model.Account;
import com.csaba.connector.model.Amount;
import com.csaba.connector.model.HistoryItem;
import com.csaba.util.LoggerHelper;

final class Index
{
	public int value;

	public Index( final int value )
	{
		this.value = value;
	}
}

public class AccountBalanceParser
{

	private final static Logger logger = LoggerHelper.getDefaultLogger();

	private static String parseAccountParameter( final Index index, final String value, final Source source )
			throws IOException, ParseException
	{
		final Element element = source.getNextElement(index.value, "ID", value, true);
		index.value = element.getEnd();
		// return with element's content
		return element.getTextExtractor().toString();
	}

	private static Amount parseAccountBalance( final Index index, final String value, final Source source )
			throws IOException, ParseException
	{
		final DecimalFormat amountFormat = CitiCodes.amountFormat.get();
		final Element element = source.getNextElement(index.value, "ID", value, true);
		index.value = element.getEnd();
		final String content = source.getPreviousStartTag(element.getBegin(), HTMLElementName.TD).getElement()
				.getTextExtractor().toString().trim();
		final String currency = content.substring(content.length() - 3);
		final String balance = content.substring(0, content.length() - 4);
		final double dAvailableBalance = amountFormat.parse(balance).doubleValue();
		return new Amount(dAvailableBalance, Currency.getInstance(currency));
	}

	private static int parseAccount( final int pos, final Source source, final Account account ) throws IOException,
			ParseException
	{

		final Index index = new Index(pos);

		// Account Type
		account.setType(parseAccountParameter(index, "PN", source));

		// Account Number
		account.setNumber(parseAccountParameter(index, "AN", source));

		// Available Balance
		account.setAvailableBalance(parseAccountBalance(index, "FB1", source));
		account.setCurrency(account.getAvailableBalance().getCurrency());

		// Booked Balance
		account.setBookedBalance(parseAccountBalance(index, "FB2", source));

		return index.value;
	}

	@SuppressWarnings( "unchecked" )
	public static Account[] parseAccountList( final Reader reader ) throws IOException, ParseException
	{
		final Source source = new Source(reader);
		final List<Account> accountList = new ArrayList<Account>();

		source.fullSequentialParse();

		final List elements = source.getAllElements("ID", "CN", true);
		for ( int i = 0; i < elements.size(); i++ )
		{
			final Element element = (Element) elements.get(i);
			final String nameAccountTypeGroupe = source.getPreviousStartTag(element.getBegin(), HTMLElementName.TD)
					.getElement().getTextExtractor().toString().trim();

			final int l = i + 1;
			int beginNextElement = 0;
			if ( l < elements.size() )
			{
				final Element nextElement = (Element) elements.get(l);
				beginNextElement = nextElement.getBegin();
			}
			else
			{
				beginNextElement = source.getEnd();
			}
			int endDetailElement = element.getEnd();
			do
			{
				final Element elementPN = source.getNextElement(endDetailElement, "ID", "PN", true);

				if ( elementPN != null && elementPN.getBegin() < beginNextElement )
				{
					final Account account = new Account();
					accountList.add(account);
					endDetailElement = parseAccount(endDetailElement, source, account);
					account.setName(nameAccountTypeGroupe);
				}
				else
				{
					endDetailElement = 0;
				}
			}
			while ( endDetailElement > 0 );
		}

		final Account[] result = new Account[accountList.size()];
		for ( int i = 0; i < accountList.size(); i++ )
		{
			result[i] = accountList.get(i);
		}

		return result;
	}

	/**
	 * @param args
	 * @throws IOException
	 * @throws MalformedURLException
	 * @throws ParseException
	 */
	public static void main( final String[] args ) throws MalformedURLException, IOException, ParseException
	{
		LoggerHelper.initLogger(Level.FINE);
		System.out.println(args[0]);

		final FileInputStream fis = new FileInputStream(args[0]);
		final Account[] accounts = parseAccountList(new InputStreamReader(fis, Charset.forName("UTF-8")));
		for ( final Account acc : accounts )
		{
			logger.info("acc: " + acc);
			logger.info(acc.getType());
			logger.info(acc.getName());
			logger.info(acc.getNumber());
			logger.info(acc.getAvailableBalance().getAmount()
					+ acc.getAvailableBalance().getCurrency().getCurrencyCode());
			logger.info(acc.getBookedBalance().getAmount() + acc.getBookedBalance().getCurrency().getCurrencyCode());
		}

		// AccountHistory
		final FileInputStream fis2 = new FileInputStream(args[1]);
		final HistoryItem[] items = AccountHistoryParser.parseAccountHistoryList(new InputStreamReader(fis2,
				CitiCodes.HTML_CHARSET), accounts[0]);
		for ( final HistoryItem item : items )
		{
			logger.info(item.toString());
		}

	}
}
